﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;



namespace Tornado
{
    public class SignalReceiver
    {

        Queue<byte[]> buffer = new Queue<byte[]>();
        int SIZE_OF_PACKET = SignalPacket.SIZE + 2; // size of Password

        int _UDPPort;
        private UdpClient udpSocket;

        volatile bool stopped = false;

        public int UDPPort
        {
            get { return _UDPPort; }
        }

        public SignalReceiver(int UDPPort = 15243)
        {
            this._UDPPort = UDPPort;
        }

        IPEndPoint sender = new IPEndPoint(0, 0);
        AsyncCallback socketAsyncCallback = null;
        public void BeginReceive()
        {
            if (socketAsyncCallback == null)
            {
                socketAsyncCallback = new AsyncCallback(socketReceived);
            }
            buffer.Clear();
            udpSocket = new UdpClient(UDPPort);
            udpSocket.EnableBroadcast = true;
            stopped = false;
            udpSocket.BeginReceive(socketAsyncCallback, null);
        }

        void socketReceived(IAsyncResult result)
        {
            if (!stopped)
            {
                byte[] b = udpSocket.EndReceive(result, ref sender);
                if (b.Length == SIZE_OF_PACKET)
                {
                    Array.Reverse(b);
                    short pass = BitConverter.ToInt16(b, 6);
                    if (((pass == Config.HostPassword) || (pass == Config.GuestPassword)) && (Config.isAcceptCmd(b[5], pass)))
                    {
                        buffer.Enqueue(b);
                    }
                }
                udpSocket.BeginReceive(socketAsyncCallback, null);
            }
        }

        static string StopException = "Stop by user!";
        public SignalPacket NextCommand()
        {
            byte[] b;
            while (true && !stopped)
            {
                while (buffer.Count == 0 && !stopped) ;

                if (stopped)
                {
                    throw new Exception(StopException);
                }
                b = buffer.Dequeue();
                SignalPacket p;
                p.Code = b[5];
                p.ExtensionCode = b[4];
                p.Argument = new byte[4];
                Array.Copy(b, p.Argument, 4);
                return p;
            }
            throw new Exception(StopException);
        }

        public void StopReceive()
        {
            stopped = true;

            udpSocket.Close();

        }
    }
}
